package de.geraldschenke.tictactoe;

import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import de.geraldschenke.tictactoe.common.GameProperties;
import de.geraldschenke.tictactoe.common.PlayerEvent;
import de.geraldschenke.tictactoe.common.RemotePlayer;
import de.geraldschenke.tictactoe.common.Stone;
import de.geraldschenke.tictactoe.server.GameThread;

@SuppressLint("ViewConstructor")
public class TicTacToeView extends View {

	public Stone[][] mBoard;
	private final Bitmap image_x;
	private final Bitmap image_o;
	private final Bitmap image_empty;
	private final Toast mToastText;
	private int height = 1;
	private int width = 1;
	private final GameThread mGameThread;
	private List<RemotePlayer> players = new ArrayList<RemotePlayer>();

	@SuppressLint("ShowToast")
	public TicTacToeView(final Context context, GameProperties gp, GameThread gameThread) {
		super(context);
		mGameThread = gameThread;
		mBoard = new Stone[gp.boardSize][gp.boardSize];
		image_x = BitmapFactory.decodeResource(getResources(), R.drawable.cross);
		image_o = BitmapFactory.decodeResource(getResources(), R.drawable.circle);
		image_empty = BitmapFactory.decodeResource(getResources(), R.drawable.empty);
		mToastText = Toast.makeText(context, "", Toast.LENGTH_SHORT);
	}

	public void displayText(final String message) {
		mToastText.cancel();
		mToastText.setText(message);
		mToastText.show();
	}

	protected void onDraw(final Canvas canvas) {
		for (int i = 0; i < getBoardSize(); i++) {
			for (int j = 0; j < getBoardSize(); j++) {
				if (getFieldOwner(i, j) == Stone.X) {
					drawImage(canvas, i, j, image_x);
				} else if (getFieldOwner(i, j) == Stone.O) {
					drawImage(canvas, i, j, image_o);
				} else {
					drawImage(canvas, i, j, image_empty);
				}
			}
		}
		drawLines(canvas);
		super.onDraw(canvas);
	}

	@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        width = r-l;
        height = b-t;
        super.onLayout(changed, l, t, r, b);
    }
	
	private Stone getFieldOwner(int i, int j) {
		return mBoard[i][j];
	}

	public int getBoardSize() {
		return mBoard.length;
	}

	private void drawImage(final Canvas canvas, final int x, final int y, final Bitmap image) {
		int w = this.getWidth() / getBoardSize();
		int h = this.getHeight() / getBoardSize();
		canvas.drawBitmap(image, null, new Rect(x * w, y * h, (x * w) + w, (y * h) + h), new Paint());
	}

	private void drawLines(final Canvas canvas) {
		Paint blackPaint = new Paint();
		blackPaint.setARGB(255, 0, 0, 0);
		blackPaint.setAntiAlias(true);
		blackPaint.setStyle(Style.STROKE);
		blackPaint.setStrokeWidth(5);

		int w = this.getWidth() / getBoardSize();
		int h = this.getHeight() / getBoardSize();
		for (int i = 0; i < getBoardSize(); i++) {
			canvas.drawLine(w * i, 0, w * i, this.getHeight(), blackPaint);
			canvas.drawLine(0, h * i, this.getWidth(), h * i, blackPaint);
		}
	}

	public void announceWinner(Stone winner) {
		if (winner != null) {
			String msg = getContext().getString(R.string.the_winner_is_) + winner;
			Log.i("TicTacToeView.onTouchEvent", msg);
			displayText(msg);
		} else {
			String msg = getContext().getString(R.string.it_s_a_draw_);
			Log.i("TicTacToeView.onTouchEvent", msg);
			displayText(msg);
		}
	}

	public boolean onTouchEvent(final MotionEvent event){//, final GameThread gameThread) {
		Log.d("tttActivity", "onTouchEvent()");
		if (players.isEmpty()){
			return true;
		}
		int x_aux = (int) ((event.getX()-(this.getWidth()-this.width)) / (this.width / getBoardSize()));
		int y_aux = (int) ((event.getY()-(this.getHeight()-this.height)) / (this.height / getBoardSize()));

		// edgecase if event x/y pos == width/height, we end up with x_aux/y_aux
		// == boardsize. Out of range!
		if (x_aux >= getBoardSize()) {
			x_aux = getBoardSize() - 1;
		}
		if (y_aux >= getBoardSize()) {
			y_aux = getBoardSize() - 1;
		}
		Log.d("tttActivity", "onTouchEvent() view width = "+this.getWidth()+ " height = "+this.getHeight());
		Log.d("tttActivity", "onTouchEvent() onlayout width = "+this.width+ " height = "+this.height);
		Log.d("tttActivity", "onTouchEvent() x = "+ event.getX() + " y = "+ event.getY());
		Log.d("tttActivity", "onTouchEvent() x_aux = "+ x_aux +" y_aux = "+ y_aux);
		PlayerEvent playerEvent = new PlayerEvent();
		playerEvent.type = PlayerEvent.Type.SET;
		playerEvent.x = x_aux;
		playerEvent.y = y_aux;
		mGameThread.handlePlayerEvent(playerEvent);

		this.invalidate();
		return true;
	}

	public void addHumanPlayer(RemotePlayer player) {
		players.add(player);
	}
}
